package com.coderush.admin.sys.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.coderush.admin.sys.dao.MenuDao;
import com.coderush.admin.sys.dao.RoleMenuDao;
import com.coderush.admin.sys.exception.MenuException;
import com.coderush.admin.sys.model.dto.MenuAssignDto;
import com.coderush.admin.sys.model.entity.Menu;
import com.coderush.admin.sys.model.entity.RoleMenu;
import com.coderush.admin.sys.model.vo.MenuSimpleVo;
import com.coderush.admin.sys.model.vo.MenuVo;
import com.coderush.admin.sys.service.MenuService;
import com.coderush.admin.sys.service.RoleMenuService;
import com.coderush.admin.sys.mapper.RoleMenuMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author Administrator
* @description 针对表【sys_role_menu(角色和菜单)】的数据库操作Service实现
* @createDate 2025-08-29 16:36:40
*/
@Service
public class RoleMenuServiceImpl extends ServiceImpl<RoleMenuMapper, RoleMenu>
    implements RoleMenuService{

    @Resource
    private MenuDao menuDao;

    @Resource
    private RoleMenuDao roleMenuDao;

    /**
     * 查询角色已分配的菜单
     *
     * @param roleId
     * @return
     */
    @Override
    public Map<String, Object> findAssignMenu(Long roleId) throws Exception {

        if (roleId == null) {
            throw MenuException.roleIdNotExist();
        }

        // 查询系统所有菜单
        List<Menu> menuList = menuDao.findAllMenu();
        if (CollectionUtils.isEmpty(menuList)) {
            throw MenuException.menuNotExist();
        }

        List<MenuVo> menuVoList = JSONArray.parseArray(JSON.toJSONString(menuList), MenuVo.class);

        menuVoList = this.buildTree(menuVoList);

        // 将MenuVo转换成MenuSimpleVo
        List<MenuSimpleVo> menuSimpleVoList = new ArrayList<>();
        menuSimpleVoList = JSONArray.parseArray(JSON.toJSONString(menuVoList), MenuSimpleVo.class);

        // 查询当前角色已经分配的菜单Ids
        List<Long> roleMenuIds = roleMenuDao.findByRoleIds(List.of(roleId));

        List<String> roleMenuIdsStr = new ArrayList<>();
        roleMenuIdsStr = roleMenuIds.stream().map(String::valueOf).toList();

        // 将数据存储到Map中进行返回
        Map<String , Object> result = new HashMap<>() ;
        result.put("sysMenuList" , menuSimpleVoList) ;
        result.put("roleMenuIds" , roleMenuIdsStr) ;

        return result;
    }

    /**
     * 角色分配菜单
     *
     * @param menuAssignDto
     * @return
     */
    @Override
    public boolean assignMenu(MenuAssignDto menuAssignDto) throws Exception {

        // 物理删除角色ID对应的所有菜单
        roleMenuDao.deleteByRoleId(menuAssignDto.getRoleId());

        // 如果没有被选中的菜单，则直接返回
        if (CollectionUtils.isEmpty(menuAssignDto.getMenuIdList())) {
            return true;
        }

        // 保存角色对应的菜单
        roleMenuDao.doAssign(menuAssignDto);

        return true;
    }

    private List<MenuVo> buildTree(List<MenuVo> sysMenuList) {
        //sysMenuList所有菜单集合
        //创建list集合，用于封装最终的数据
        List<MenuVo> trees = new ArrayList<>();
        //遍历所有菜单集合
        for(MenuVo sysMenu : sysMenuList) {
            //找到递归操作入口，第一层的菜单
            //条件： parent_id=0
            if(sysMenu.getParentId() == 0) {
                //根据第一层，找下层数据，使用递归完成
                //写方法实现找下层过程，
                // 方法里面传递两个参数：第一个参数当前第一层菜单，第二个参数是所有菜单集合
                trees.add(findChildren(sysMenu,sysMenuList));
            }
        }
        return trees;
    }

   private MenuVo findChildren(MenuVo sysMenu, List<MenuVo> sysMenuList) {
        // SysMenu有属性 private List<SysMenu> children;封装下一层数据
        sysMenu.setChildren(new ArrayList<>());
        //递归查询
        // sysMenu的id值 和  sysMenuList中parentId相同
        for(MenuVo it : sysMenuList) {
            //判断id 和  parentid是否相同
            if(sysMenu.getId().longValue() == it.getParentId().longValue()) {
                // it就是下层数据，进行封装
                sysMenu.getChildren().add(findChildren(it,sysMenuList));
            }
        }
        return sysMenu;
    }
}




